#pragma once

#include <iostream>
#include "Connection.hpp"

class Channel : public Connection
{
public:
    Channel(int sockfd, InetAddr &client) : _sockfd(sockfd), _client_addr(client)
    {
        SetNonBlock(_sockfd);
    }
    
    void Recver() override
    {
        char buffer[1024];
        while (true)
        {
            buffer[0] = 0; // 置空buffer
            ssize_t n = recv(_sockfd, buffer, sizeof(buffer) - 1, 0);
            if (n > 0)
            {
                buffer[n] = 0;
                _inbuffer += buffer;
            }
            else if (n == 0)
            {
                Expecter();
                return;
            }
            else
            {
                //已读完
                if (errno == EAGAIN || errno == EWOULDBLOCK)
                    break;
                else if (errno == EINTR)//被信号中断，继续读
                    continue;
                else
                {
                    Expecter();
                    return;
                }
            }
        }
        LOG(Loglevel::DEBUG) << "Channel Recv:\n"
                             << _inbuffer;

        //如果接收缓冲区不为空 ---有数据，回调交给上层处理
        if (!_inbuffer.empty())
            _outbuffer += _handler(_inbuffer);

        //如果发送缓冲区不为空，则发送数据
        if (!_outbuffer.empty())
            Sender();
    }

    void Sender() override
    {
        while (true)
        {
            ssize_t n = send(_sockfd, _outbuffer.c_str(), _outbuffer.size(), 0);
            if (n > 0)
            {
                _outbuffer.erase(0, n);
                if (_outbuffer.empty())
                    break;
            }
            else if (n == 0)
            {
                break;
            }
            else
            {
                if (errno == EAGAIN || errno == EWOULDBLOCK)
                    break;
                else if (errno == EINTR)
                    continue;
                else
                {
                    Expecter();
                    return;
                }
            }
        }

        //如果写缓存冲为空，则设置事件为不就绪状态，无法发送数据
        //不为空，则写事件就绪
        if (_outbuffer.empty())
            GetOwner()->EnableReadWrite(_sockfd, true, false);
        else
            GetOwner()->EnableReadWrite(_sockfd, true, true);
    }

    void Expecter() override
    {
        GetOwner()->DelConnection(_sockfd);
    }
    int GetSockfd() override
    {
        return _sockfd;
    }
    std::string &InBuffer()
    {
        return _inbuffer;
    }
    void AddOutBuffer(const std::string &out)
    {
        _outbuffer += out;
    }
    ~Channel()
    {
    }

private:
    //改缓冲区所属的套接字
    int _sockfd;
    // 缓冲区
    std::string _inbuffer;
    std::string _outbuffer;

    // client信息
    InetAddr _client_addr;
};